/*
 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 * 
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
/*
 * @OSF_FREE_COPYRIGHT@
 */
/* 
 * Mach Operating System
 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
/*
 */
/*
 *	File:	mach/mach_port.defs
 *	Author:	Rich Draves
 *
 *	Exported kernel calls.
 */

subsystem
#if	KERNEL_SERVER || KOBJECT_SERVER
	KernelServer
#endif	/* KERNEL_SERVER || KOBJECT_SERVER */
	  task 3400;

#include <mach/std_types.defs>
#include <mach/mach_types.defs>
#include <mach_debug/mach_debug_types.defs>

#if !KERNEL && !LIBSYSCALL_INTERFACE
#define PREFIX(NAME) _kernelrpc_ ## NAME
#else
#define PREFIX(NAME) NAME
#endif

/*
 * Sandbox builds task.defs with KERNEL_SERVER defined when generating the map
 * of MIG routine names to message IDs.
 * The MIG routine names need to be kept stable so as to not break Sandbox
 * profiles.
 */
#if	KERNEL_SERVER && !SANDBOX_COMPILER
#define MIG_SERVER_SUFFIX(NAME) NAME ## _mig
#else
#define MIG_SERVER_SUFFIX(NAME) NAME
#endif


/*
 * OBSOLETE interfaces, removed from kernel
 */
#if KERNEL_SERVER
skip; /* task_create */
#else
routine task_create(
		target_task	: task_t;
		ledgers		: ledger_array_t;
		inherit_memory	: boolean_t;
	out	child_task	: task_t);
#endif

/*
 *	Destroy the target task, causing all of its threads
 *	to be destroyed, all of its IPC rights to be deallocated,
 *	and all of its address space to be deallocated.
 */
routine task_terminate(
		target_task	: task_t);

/*
 *	Returns the set of threads belonging to the target task.
 *  [Polymorphic] This routine returns thread port with the same 
 *  flavor as that of the task port passed in.
 */
routine
#ifdef KERNEL_SERVER
task_threads_from_user(
		port		: mach_port_t;
#else
task_threads(
		target_task	: task_inspect_t;
#endif
	out	act_list	: thread_act_array_t);


/*
 *	Stash a handful of ports for the target task; child
 *	tasks inherit this stash at task_create time.
 */
#if LIBSYSCALL_INTERFACE
routine	mach_ports_register(
		target_task	: task_t;
		init_port_set	: mach_port_array_t =
					^array[] of mach_port_t);
#else
routine	_kernelrpc_mach_ports_register3(
		target_task	: task_t;
		port1           : mach_port_t;
		port2           : mach_port_t;
		port3           : mach_port_t);
#endif

/*
 *	Retrieve the stashed ports for the target task.
 */
#if LIBSYSCALL_INTERFACE
routine	mach_ports_lookup(
		target_task	: task_t;
	out	init_port_set	: mach_port_array_t =
					^array[] of mach_port_t);
#else
routine	_kernelrpc_mach_ports_lookup3(
		target_task	: task_t;
	out	port1		: mach_port_t;
	out	port2		: mach_port_t;
	out	port3		: mach_port_t);
#endif

/*
 *      Returns information about the target task.
 */
#ifdef KERNEL_SERVER
routine task_info_from_user(
                target_task     : mach_port_t;
                flavor          : task_flavor_t;
        out     task_info_out   : task_info_t, CountInOut);
#else
routine task_info(
                target_task     : task_name_t;
                flavor          : task_flavor_t;
        out     task_info_out   : task_info_t, CountInOut);

#endif

/*
 * Set task information.
 */
routine	task_set_info(
		target_task	: task_t;
		flavor		: task_flavor_t;
		task_info_in	: task_info_t);

/*
 *	Increment the suspend count for the target task.
 *	No threads within a task may run when the suspend
 *	count for that task is non-zero.
 */
routine	task_suspend(
		target_task	: task_read_t);


/*
 *	Decrement the suspend count for the target task,
 *	if the count is currently non-zero.  If the resulting
 *	suspend	count is zero, then threads within the task
 *	that also have non-zero suspend counts may execute.
 */
routine	task_resume(
		target_task	: task_read_t);

/*
 *	Returns the current value of the selected special port
 *	associated with the target task.
 */
routine
#ifdef KERNEL_SERVER
task_get_special_port_from_user(
		port		: mach_port_t;
#else
task_get_special_port(
		task		: task_inspect_t;
#endif
		which_port	: int;
	out	special_port	: mach_port_t);


/*
 *	Set one of the special ports associated with the
 *	target task.
 */
routine
#if	KERNEL_SERVER && !SANDBOX_COMPILER
task_set_special_port_from_user(
#else
task_set_special_port(
#endif
		task		: task_t;
		which_port	: int;
		special_port	: mach_port_t);

/*
 *	Create a new thread within the target task, returning
 *	the port representing the first thr_act in that new thread.  The
 *	initial execution state of the thread is undefined.
 */
routine
#ifdef KERNEL_SERVER
thread_create_from_user(
#else
thread_create(
#endif
		parent_task	: task_t;
	out	child_act	: thread_act_t);

/*
 *      Create a new thread within the target task, returning
 *      the port representing that new thread.  The new thread 
 *	is not suspended; its initial execution state is given
 *	by flavor and new_state. Returns the port representing 
 *	the new thread.
 */
routine
#ifdef KERNEL_SERVER
thread_create_running_from_user(
#else
thread_create_running(
#endif
                parent_task     : task_t;
                flavor          : thread_state_flavor_t;
                new_state       : thread_state_t;
        out     child_act       : thread_act_t);

/*
 * Set an exception handler for a task on one or more exception types.
 * These handlers are invoked for all threads in the task if there are
 * no thread-specific exception handlers or those handlers returned an
 * error.
 */
routine	task_set_exception_ports(
		task		: task_t;
		exception_mask	: exception_mask_t;
		new_port	: mach_port_t;
		behavior	: exception_behavior_t;
		new_flavor	: thread_state_flavor_t);


/*
 * Lookup some of the old exception handlers for a task
 */
routine
#if KERNEL_SERVER
task_get_exception_ports_from_user(
		port        : mach_port_t;
#else
task_get_exception_ports(
		task		: task_t;
#endif
		exception_mask	: exception_mask_t;
	  out	masks		: exception_mask_array_t;
	  out	old_handlers	: exception_handler_array_t, SameCount;
	  out	old_behaviors	: exception_behavior_array_t, SameCount;
	  out	old_flavors	: exception_flavor_array_t, SameCount);


/*
 * Set an exception handler for a thread on one or more exception types.
 * At the same time, return the previously defined exception handlers for
 * those types.
 */
routine	task_swap_exception_ports(
		task		: task_t;
		exception_mask	: exception_mask_t;
		new_port	: mach_port_t;
		behavior	: exception_behavior_t;
		new_flavor	: thread_state_flavor_t;
	  out	masks		: exception_mask_array_t;
	  out	old_handlers	: exception_handler_array_t, SameCount;
	  out	old_behaviors	: exception_behavior_array_t, SameCount;
	  out	old_flavors	: exception_flavor_array_t, SameCount);

/*
 * OBSOLETE interfaces, removed from kernel
 */
#if KERNEL_SERVER
skip;
skip;
#else
routine lock_set_create(
		task		: task_t;
	out	new_lock_set	: lock_set_t;
		n_ulocks	: int;
		policy		: int);

routine lock_set_destroy(
		task		: task_t;
		lock_set	: lock_set_t);
#endif

/*
 * Create and destroy semaphore synchronizers on a
 * per-task basis (i.e. the task owns them).
 */

routine semaphore_create(
		task		: task_t;
	out	semaphore	: semaphore_t;
		policy		: int;
		value		: int);

routine semaphore_destroy(
		task		: task_t;
		semaphore	: semaphore_consume_ref_t);

/*
 * Set/get policy information for a task.
 * (Approved Mac OS X microkernel interface)
 */

routine task_policy_set(
	task			: task_policy_set_t;
	flavor			: task_policy_flavor_t;
	policy_info		: task_policy_t);

routine task_policy_get(
	task			: task_policy_get_t;
	flavor			: task_policy_flavor_t;
out	policy_info		: task_policy_t, CountInOut;
inout	get_default		: boolean_t);

/*
 *	OBSOLETE interfaces, removed from kernel.
 */
#if KERNEL_SERVER
skip; /* task_sample */
skip; /* task_policy */
skip; /* task_set_emulation */
skip; /* task_get_emulation_vector */
skip; /* task_set_emulation_vector */
skip; /* task_set_ras_pc */
skip; /* task_zone_info */
skip; /* task_assign */
skip; /* task_assign_default */
skip; /* task_get_assignment */
skip; /* task_set_policy */
#else
routine task_sample(
		task		: task_t;
		reply		: mach_port_make_send_t);

routine task_policy(
	task			: task_t;
	policy			: policy_t;
	base			: policy_base_t;
	set_limit		: boolean_t;
	change			: boolean_t);

routine task_set_emulation(
		target_port	: task_t;
		routine_entry_pt: vm_address_t;
		routine_number  : int);	

routine task_get_emulation_vector(
		task		: task_t;
	out	vector_start	: int;
	out	emulation_vector: emulation_vector_t);

routine task_set_emulation_vector(
		task		: task_t;
		vector_start	: int;
		emulation_vector: emulation_vector_t);


routine task_set_ras_pc(
		target_task     : task_t;
		basepc          : vm_address_t;
		boundspc        : vm_address_t);

routine task_zone_info(
		target_task	: task_inspect_t;
	out	names		: mach_zone_name_array_t,
					Dealloc;
	out	info		: task_zone_info_array_t,
					Dealloc);

routine task_assign(
		task		: task_t;
		new_set		: processor_set_t;
		assign_threads	: boolean_t);

routine task_assign_default(
		task		: task_t;
		assign_threads	: boolean_t);

routine task_get_assignment(
		task		: task_inspect_t;
	out	assigned_set	: processor_set_name_t);

routine task_set_policy(
	task			: task_t;
	pset			: processor_set_t;
	policy			: policy_t;
	base			: policy_base_t;
	limit			: policy_limit_t;
	change			: boolean_t);
#endif

/*
 * Read the selected state which is to be installed on new 
 * threads in the task as they are created.
 */
routine task_get_state(
		task		: task_read_t;
		flavor		: thread_state_flavor_t;
	out	old_state	: thread_state_t, CountInOut);
 
/*
 * Set the selected state information to be installed on
 * all subsequently created threads in the task.
 */
routine	task_set_state(
		task		: task_t;
		flavor		: thread_state_flavor_t;
		new_state	: thread_state_t);

/*
 * Change the task's physical footprint limit (in MB).
 */
routine task_set_phys_footprint_limit(
		task		: task_t;
		new_limit	: int;
	out old_limit	: int);

routine MIG_SERVER_SUFFIX(task_suspend2)(
		target_task : task_read_t;
	out suspend_token : task_suspension_token_t);

routine MIG_SERVER_SUFFIX(task_resume2)(
		suspend_token : task_suspension_token_t);

routine task_purgable_info(
		task 		: task_inspect_t;
	out	stats		: task_purgable_info_t);

routine task_get_mach_voucher(
		task		: task_read_t;
		which		: mach_voucher_selector_t;
	out	voucher		: ipc_voucher_t);

routine task_set_mach_voucher(
		task		: task_t;
		voucher		: ipc_voucher_t);

routine task_swap_mach_voucher(
		task		: task_t;
		new_voucher	: ipc_voucher_t;
	inout	old_voucher	: ipc_voucher_t);

routine task_generate_corpse(
		task		:task_read_t;
	out	corpse_task_port:mach_port_t);

routine task_map_corpse_info(
		task		:task_t;
		corspe_task	:task_read_t;
	out	kcd_addr_begin	:vm_address_t;
	out	kcd_size	:uint32_t);

routine task_register_dyld_image_infos(
        task            :task_t;
        dyld_images     :dyld_kernel_image_info_array_t);

routine task_unregister_dyld_image_infos(
        task            :task_t;
        dyld_images     :dyld_kernel_image_info_array_t);

routine task_get_dyld_image_infos(
        task            :task_read_t;
    out dyld_images     :dyld_kernel_image_info_array_t);

routine task_register_dyld_shared_cache_image_info(
        task                :task_t;
        dyld_cache_image    :dyld_kernel_image_info_t;
        no_cache            :boolean_t;
        private_cache       :boolean_t);

routine task_register_dyld_set_dyld_state(
        task           :task_t;
        dyld_state     :uint8_t);

routine task_register_dyld_get_process_state(
        task                :task_t;
    out dyld_process_state  :dyld_kernel_process_info_t);

routine task_map_corpse_info_64(
		task		:task_t;
		corspe_task	:task_read_t;
	out	kcd_addr_begin	:mach_vm_address_t;
	out	kcd_size	:mach_vm_size_t);

routine task_inspect(
	    task     : task_inspect_t;
	    flavor   : task_inspect_flavor_t;
	out info_out : task_inspect_info_t, CountInOut);

routine task_get_exc_guard_behavior(
		task	 : task_inspect_t;
	out behavior : task_exc_guard_behavior_t);

routine task_set_exc_guard_behavior(
		task	 : task_t;
		behavior : task_exc_guard_behavior_t);

skip;

#if KERNEL || (!KERNEL && !LIBSYSCALL_INTERFACE)
routine PREFIX(mach_task_is_self)(
		task     : task_name_t;
	out is_self  : boolean_t);
#else
	/* Do not generate header, use the one in mach_init.h */
	skip;
#endif

routine task_dyld_process_info_notify_register(
		target_task : task_read_t;
		notify   	: mach_port_make_send_t);

routine task_create_identity_token(
	    task     : task_t;
	out	token    : task_id_token_t);

routine task_identity_token_get_task_port(
	    token    : task_id_token_t;
		flavor   : task_flavor_t;
	out task_port: mach_port_t);

routine task_dyld_process_info_notify_deregister(
		target_task : task_read_t;
		notify   	: mach_port_name_t);

routine task_get_exception_ports_info(
		port : mach_port_t;
		exception_mask	: exception_mask_t;
	out	masks		: exception_mask_array_t;
	out	old_handlers_info	: exception_handler_info_array_t, SameCount;
	out	old_behaviors	: exception_behavior_array_t, SameCount;
	out	old_flavors	: exception_flavor_array_t, SameCount);

routine task_test_sync_upcall(
	task	: task_t;
	port	: mach_port_t);

routine task_set_corpse_forking_behavior(
		task	 : task_t;
		behavior : task_corpse_forking_behavior_t);

routine task_test_async_upcall_propagation(
	task	: task_t;
	port	: mach_port_t;
	qos	: int;
	iotier	: int);

routine task_map_kcdata_object_64(
		task		:task_t;
		kcdata_object	:kcdata_object_t;
	out	kcd_addr_begin	:mach_vm_address_t;
	out	kcd_size	:mach_vm_size_t);

/*
 * When used in conjunction with thread_adopt_exception_handler, we call this a
 * hardened mach exception handler, and it adds additional security guarantees to this exception port:
 *		1. Enforces only a subset of exceptions, behaviours, and flavors
 *			may be used with this port
 *      2. The `new_exception_port` must be created using MPO_EXCEPTION_PORT (implicitly immovable)
 *      3. When using *STATE* behaviors of exception handling, only the PC is allowed to be set.
 *		4. Setting the PC in an exception handler must be signed using a diversifier of
 *			signed_pc_key (if non-zero). You can pre-sign your PC
 *			state and then throw away the key to ensure that only a limited
 *			set of PC's may be used with this exception handler
 *      5. Calling `[task,thread,host]_set_exception_ports` if you have the IPC_ONLY_ONE_EXCEPTION_PORT
 *			entitlement is disallowed, and you must use this hardened exception flow.
 *		If used with the traditional set_exception_ports functions, these
 *		security guarantees do not apply.
 *		You can only call this once per task.
 *
 *      See tests/ipc/hardened_exceptions.c for examples.
 */
routine task_register_hardened_exception_handler(
			task : task_t;
			signed_pc_key : uint32_t;
			exceptions_allowed : exception_mask_t;
			behaviors_allowed : exception_behavior_t;
			flavors_allowed	: thread_state_flavor_t;
			new_exception_port : mach_port_t);


/* vim: set ft=c : */

